#include "Debug.h"
#include "SubMesh.h"
#include "SeamCutter.h"


SubMesh::SubMesh(double _radius, VertexBase* _vertex, map<int,TriangleBase*> _triangles, SubMesh* _prevSubMesh)
{
	radius = _radius;
	vertex = _vertex;
	allTriangles = _triangles;
	prevSubMesh = _prevSubMesh;

	if(radius == 0)	
		triangles = vertex->getAdjacentTriangles();		
	else	
	{		
		set<TriangleBase*>* newEntries = new set<TriangleBase*>();
		for(uint i =0; i<prevSubMesh->getTriangles().size(); i++)	
			newEntries->insert(prevSubMesh->getTriangles()[i]);
		
		while( addAdjacentTriangles(newEntries) ) {};

		triangles.clear();
		for (set<TriangleBase*>::iterator it=newEntries->begin(); it!=newEntries->end(); ++it)
			triangles.push_back(*it);	
		delete newEntries;
	}
	for(int i =0; i<triangles.size(); i++)		
		countEdges(triangles[i]->getSides());

	//valid = triangles.size() == allTriangles.size() ? false : true;

	bool allBorderEdges = false;
	for (map<EdgeBase*, int>::iterator it=edgeCounter.begin(); it!=edgeCounter.end(); ++it)	
		if(it->second == 1)
			allBorderEdges = true;

	if( allBorderEdges )	
		valid = true;		
	else	
		valid = triangles.size() == allTriangles.size() ? false : true;

	//cout << "Submesh Valid: " << valid << endl;
	//if( vertex->getNum() == 0)
	//{
	//	cout << "\tValidity: " << triangles.size() << " == " << allTriangles.size() << endl;

	//	cout << "\tSubMesh Faces: ";
	//	for (int i=0; i<triangles.size(); i++)
	//		cout << triangles[i]->getFaceNumber() << " ";
	//	cout << endl;

	//	cout << "\tBorder Edges: ";
	//	for (map<EdgeBase*, int>::iterator it=edgeCounter.begin(); it!=edgeCounter.end(); it++)
	//		if(it->second == 1)	
	//			cout << it->first->getIndex() << " ";
	//	cout << endl;		
	//	//cout << "Edge: " << it->first->index << " angle between " << it->first->start->getNum() << " and " << it->first->end->getNum() << " = " << it->first->getAngleInTriangle(vertex) << endl;
	//}
}


bool SubMesh::addAdjacentTriangles(set<TriangleBase*>* faceList)
{
	bool added = false;
	for (set<TriangleBase*>::iterator it=faceList->begin(); it!=faceList->end(); ++it)
	{
		MIntArray* adjacentIndices = (*it)->getAdjacentFaceIndices();
		for(uint j=0; j<adjacentIndices->length(); j++)	
		{
			if(allTriangles[ (*adjacentIndices)[j]]->inRadiusOf(vertex, radius))
			{
				pair<set<TriangleBase*>::iterator,bool> result = faceList->insert(allTriangles[ (*adjacentIndices)[j] ]);		
				if(result.second == true)
					added = true;
			}
		}
		delete adjacentIndices;
	}	
	return added;
}

void SubMesh::countEdges(vector<EdgeBase*> edges)
{
	for(int h=0; h<3; h++)
		edgeCounter[edges[h]] = edgeCounter.count(edges[h]) == 0 ?	1 : edgeCounter[edges[h]] + 1;
}

bool SubMesh::isValid()
{
	return valid;

	/*if(prevSubMesh == NULL)
		return true;
	else if(prevSubMesh->getTriangles().size() == this->getTriangles().size() )
		return false;
	return true;*/
}

SubMesh::~SubMesh(void)
{
}

void SubMesh::printFaces()
{
	cout << "\tFaces: ";
	for(int i=0; i<triangles.size(); i++)
		cout << triangles[i]->getNum() << ", ";
	cout << endl;
	cout << "\tBoundary Edges: ";
	for (map<EdgeBase*, int>::iterator it=edgeCounter.begin(); it!=edgeCounter.end(); ++it)	
		if(it->second == 1)		
			cout << it->first->getNum() << "(" << it->second << "), ";		
	cout << endl;
}

double SubMesh::getDistortionAtVertexAtRadiusFromSubmesh()
{
	if(vertex->onBoundary() && vertex->sumAngles() < 360)		
		return 0;	
	double total = 0;
	for (map<EdgeBase*, int>::iterator it=edgeCounter.begin(); it!=edgeCounter.end(); ++it)	
		if(it->second == 1)	
		{
			//cout << "Edge: " << it->first->getIndex() << " angle between " << it->first->getStart()->getNum() << " and " << it->first->getEnd()->getNum() << " = " << it->first->getAngleInTriangle(vertex) << endl;
			total+= it->first->getAngleInTriangle(vertex);	
		}
	total = ((360 - total)/360);
	if(total < 0.0000001 && total > -0.0000001)
		total =0;
	return abs(total);
}

void SubMesh::printDistortionProcess()
{
	if(vertex->onBoundary() && vertex->sumAngles() < 360)		
		cout << "On Boundary and Developable\n";
	double total = 0;
	for (map<EdgeBase*, int>::iterator it=edgeCounter.begin(); it!=edgeCounter.end(); ++it)	
		if(it->second == 1)	
		{
			total+= it->first->getAngleInTriangle(vertex);	
			cout << "Angle between " << it->first->getStart()->getNum() << " and " << it->first->getEnd()->getNum() << " = " << it->first->getAngleInTriangle(vertex) << " =>" << total << endl;
		}
	double result = (double)360.0 - total;
	if(result < 0.0001 && result > -0.0001)
		result =0;
	cout << "(360.0 - total) = " << result <<endl;
	result = result/360;
	cout << "/360 = " <<  result <<endl << endl;
}


double SubMesh::getRadius()
{
	return radius;
}

vector<TriangleBase*> SubMesh::getTriangles()
{
	return triangles;
}

bool orderVerts(VertexBase* v1, VertexBase* v2)
{
	if(v1->getNum() <= v2->getNum())
		return true;
	return false;
}

vector<VertexBase*> SubMesh::getVerticies()
{
	set<VertexBase*> vertSet;
	for(int i=0; i<triangles.size(); i++)
	{
		vector<VertexBase*> corners = triangles[i]->getCorners();
		for(int j=0; j<corners.size(); j++)
			vertSet.insert(corners[j]);
	}
	vector<VertexBase*> vertices;
	for (set<VertexBase*, int>::iterator it=vertSet.begin(); it!=vertSet.end(); ++it)			
		vertices.push_back(*it);	
	sort(vertices.begin(), vertices.end(), orderVerts);
	return vertices;
}


